#if UNITY_EDITOR

using System.IO;
using System.Reflection;
using System.Text.RegularExpressions;
using UnityEditor;
using UnityEditor.Callbacks;
using UnityEditorInternal;
using UnityEngine;

public class DebugRedirect
{
    private const string DEBUG_FILE_PATH = "Assets/DebugSystem/NewDebug.cs";
    
    private static readonly Regex LogRegex = new Regex(@" \(at (.+)\:(\d+)\)\r?\n");

    [OnOpenAsset(0)]
    private static bool ReposLog(int instanceID, int line)
    {
        if (EditorUtility.InstanceIDToObject(instanceID).GetType() != typeof(MonoScript)) return false;
        
        var trackInfo = GetStackTrace();

        if (string.IsNullOrEmpty(trackInfo) || !trackInfo.Contains(DEBUG_FILE_PATH)) return false;
        
        Object debuggerFile = AssetDatabase.LoadAssetAtPath(DEBUG_FILE_PATH,typeof(Object));
        if (instanceID != debuggerFile.GetInstanceID()) return false;

        var match = LogRegex.Match(trackInfo);
        if (!match.Success) return false;
 
        match = match.NextMatch();
        if (!match.Success) return false;

        var file = match.Groups[1].Value;
        var lineId = int.Parse(match.Groups[2].Value);
 
        InternalEditorUtility.OpenFileAtLineExternal(Path.Combine(GetProjectPath(), file),lineId);
        return true;
    }

    private static string GetStackTrace()
    {
        var editorWindowAssembly = typeof(EditorWindow).Assembly;
        var consoleWindowType =editorWindowAssembly.GetType("UnityEditor.ConsoleWindow");
    
        var consoleWindowFieldInfo = consoleWindowType.GetField(
            "ms_ConsoleWindow", BindingFlags.Static | BindingFlags.NonPublic);
 
        var consoleWindow = consoleWindowFieldInfo?.GetValue(null) as EditorWindow;
 
        if (consoleWindow != EditorWindow.focusedWindow)
        {
            return null;
        }
 
        var activeTextFieldInfo = consoleWindowType.GetField(
            "m_ActiveText", BindingFlags.Instance | BindingFlags.NonPublic);
 
        return (string)activeTextFieldInfo?.GetValue(consoleWindow);
    }
    
    private static string GetProjectPath() => new DirectoryInfo(Application.dataPath).Parent?.FullName;
}

#endif